home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 February: Tool Chest / Dev.CD Feb 94.toast / Tool Chest / Development Platforms / AppsToGo / AppsToGo.src / DTS.Lib / StringUtils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-18  |  12.8 KB  |  654 lines  |  [TEXT/MPS ]

  1. /*
  2. **    Apple Macintosh Developer Technical Support
  3. **
  4. **    Collection of String Utilities for DTS Sample code
  5. **
  6. **    File:        StringUtils.c
  7. **
  8. **    Copyright © 1988-1993 Apple Computer, Inc.
  9. **    All rights reserved.
  10. */
  11.  
  12. /* You may incorporate this sample code into your applications without
  13. ** restriction, though the sample code has been provided "AS IS" and the
  14. ** responsibility for its operation is 100% yours.  However, what you are
  15. ** not permitted to do is to redistribute the source as "DSC Sample Code"
  16. ** after having made changes. If you're going to re-distribute the source,
  17. ** we require that you make it clear in the source that the code was
  18. ** descended from Apple Sample Code, but that you've made changes. */
  19.  
  20. #ifndef __MEMORY__
  21. #include <Memory.h>
  22. #endif
  23.  
  24. #ifndef __STRINGUTILS__
  25. #include "StringUtils.h"
  26. #endif
  27.  
  28.  
  29.  
  30. /* These functions should be linked into whatever segment holds main().  This will
  31. ** guarantee that the functions will always be in memory when called.  It is important
  32. ** that they are in memory, because if a pointer is passed in that points into an
  33. ** unlocked handle, the mere fact that the code needs to get loaded may cause the
  34. ** handle that is pointed into to move.  If you stick to these string functions,
  35. ** you will not have to worry about the handle moving when the string function is
  36. ** called.  If you have your own string functions, and you wish the same safety
  37. ** factor, link the string handling code into the same segment as main(), as you
  38. ** do with these string functions. */
  39.  
  40. static short    gBase;
  41. static Boolean    gHandleChars;
  42.  
  43.  
  44.  
  45. /*****************************************************************************/
  46. /*****************************************************************************/
  47. /*****************************************************************************/
  48.  
  49.  
  50.  
  51. /* Return the length of the c-string.  (Same as strlen, but this function isn't
  52. ** part of the string library.  The entire library may be more than you wish to
  53. ** link into the code segment that holds main, so this (and other) standard
  54. ** library function has been duplicated here. */
  55.  
  56. #pragma segment StringUtils
  57. short    clen(char *cptr)
  58. {
  59.     short    i;
  60.  
  61.     for (i = 0; cptr[i]; ++i);
  62.     return(i);
  63. }
  64.  
  65.  
  66.  
  67. /*****************************************************************************/
  68.  
  69.  
  70.  
  71. /* Catenate two c-strings. */
  72.  
  73. #pragma segment StringUtils
  74. char    *ccat(char *s1, char *s2)
  75. {
  76.     ccpy(s1 + clen(s1), s2);
  77.     return(s1);
  78. }
  79.  
  80.  
  81.  
  82. /*****************************************************************************/
  83.  
  84.  
  85.  
  86. /* Copy a c-string. */
  87.  
  88. #pragma segment StringUtils
  89. char    *ccpy(char *s1, char *s2)
  90. {
  91.     char    *c1, *c2;
  92.  
  93.     c1 = s1;
  94.     c2 = s2;
  95.     while (*c1++ = *c2++);
  96.     return(s1);
  97. }
  98.  
  99.  
  100.  
  101. /*****************************************************************************/
  102.  
  103.  
  104.  
  105. /* Compare two pascal-strings. */
  106.  
  107. #pragma segment StringUtils
  108. short    pcmp(StringPtr s1, StringPtr s2)
  109. {
  110.     short    i, len;
  111.     char    j;
  112.  
  113.     if ((len = s1[0]) > s2[0]) len = s2[0];
  114.  
  115.     for (i = 1; i <= len; ++i)
  116.         if (j = s1[i] - s2[i]) return(j);
  117.  
  118.     return(s1[0] - s2[0]);
  119. }
  120.  
  121.  
  122.  
  123. /*****************************************************************************/
  124.  
  125.  
  126.  
  127. /* Catenate two pascal-strings. */
  128.  
  129. #pragma segment StringUtils
  130. void    pcat(StringPtr d, StringPtr s)
  131. {
  132.     short    i, j;
  133.  
  134.     if (((j = s[0]) + d[0]) > 255)
  135.         j = 255 - d[0];
  136.             /* Limit dest string to 255. */
  137.  
  138.     for (i = 0; i < j;) d[++d[0]] = s[++i];
  139. }
  140.  
  141.  
  142.  
  143. /*****************************************************************************/
  144.  
  145.  
  146.  
  147. /* Copy a pascal-string. */
  148.  
  149. #pragma segment StringUtils
  150. void    pcpy(StringPtr d, StringPtr s)
  151. {
  152.     short    i;
  153.  
  154.     i = *s;
  155.     do {
  156.         d[i] = s[i];
  157.     } while (i--);
  158. }
  159.  
  160.  
  161.  
  162. /*****************************************************************************/
  163.  
  164.  
  165.  
  166. /* Convert a c-string to a pascal-string. */
  167.  
  168. #pragma segment StringUtils
  169. void    c2p(char *cptr)
  170. {
  171.     char    len;
  172.  
  173.     BlockMove(cptr, cptr + 1, len = clen(cptr));
  174.     *cptr = len;
  175. }
  176.  
  177.  
  178.  
  179. /*****************************************************************************/
  180.  
  181.  
  182.  
  183. /* Convert a pascal-string to a c-string. */
  184.  
  185. #pragma segment StringUtils
  186. void    p2c(StringPtr cptr)
  187. {
  188.     unsigned char    len;
  189.  
  190.     BlockMove(cptr + 1, cptr, len = *cptr);
  191.     cptr[len] = 0;
  192. }
  193.  
  194.  
  195.  
  196. /*****************************************************************************/
  197. /*****************************************************************************/
  198. /*****************************************************************************/
  199.  
  200.  
  201.  
  202. /* Catenate a single character multiple times onto the designated string. */
  203.  
  204. #pragma segment StringUtils
  205. void    ccatchr(char *cptr, char c, short count)
  206. {
  207.     ccpychr(cptr + clen(cptr), c, count);
  208. }
  209.  
  210.  
  211.  
  212. /*****************************************************************************/
  213.  
  214.  
  215.  
  216. /* Convert the value into text for the base-10 number and catenate it to
  217. ** the designated string.  The value is assumed to be signed.  If you wish
  218. ** to have an unsigned decimal value, call ccatnum with a base of 10. */
  219.  
  220. #pragma segment StringUtils
  221. void    ccatdec(char *cptr, long v)
  222. {
  223.     ccatnum(cptr + clen(cptr), v, -10);        /* Catenate value base 10, signed. */
  224. }
  225.  
  226.  
  227.  
  228. /*****************************************************************************/
  229.  
  230.  
  231.  
  232. /* Convert the value into text for base-16, format it, and catenate it to the
  233. ** designated string.  ccatnum could be used, since it handles multiple bases,
  234. ** but ccathex allows for additional common formatting and padding of the
  235. ** hex value. */
  236.  
  237. #pragma segment StringUtils
  238. void    ccathex(char *cptr, char padChr, short minApnd, short maxApnd, long v)
  239. {
  240.     char    str[33], *sptr;
  241.     short    len;
  242.  
  243.     cptr += clen(cptr);            /* We're appending, so point to the end of the string. */
  244.     ccpynum(str, v, 16);        /* Generate minimum-digit hex value. */
  245.  
  246.     if ((len = clen(sptr = str)) > maxApnd)
  247.         sptr = str + len - maxApnd;
  248.  
  249.     if ((len = clen(sptr)) < minApnd)
  250.         if (padChr)
  251.             ccatchr(cptr, padChr, (minApnd - len));
  252.                 /* if we have a pad character, and if necessary, pad the string. */
  253.  
  254.     ccat(cptr, sptr);            /* Add the hex digits to the string. */
  255. }
  256.  
  257.  
  258.  
  259. /*****************************************************************************/
  260.  
  261.  
  262.  
  263. /* Convert the value into text for the designated base.  Catenate the text to
  264. ** the designated string. */
  265.  
  266. #pragma segment StringUtils
  267. void    ccatnum(char *cptr, long v, short base)
  268. {
  269.     ccpynum(cptr + clen(cptr), v, base);
  270. }
  271.  
  272.  
  273.  
  274. /*****************************************************************************/
  275.  
  276.  
  277.  
  278. #pragma segment StringUtils
  279. void    ccpychr(char *cptr, char c, short count)
  280. {
  281.     for (;count--; ++cptr) *cptr = c;
  282.     *cptr = 0;
  283. }
  284.  
  285.  
  286.  
  287. /*****************************************************************************/
  288.  
  289.  
  290.  
  291. #pragma segment StringUtils
  292. void    ccpydec(char *cptr, long v)
  293. {
  294.     ccpynum(cptr, v, -10);
  295. }
  296.  
  297.  
  298.  
  299. /*****************************************************************************/
  300.  
  301.  
  302.  
  303. #pragma segment StringUtils
  304. void    ccpyhex(char *cptr, char padChr, short minApnd, short maxApnd, long v)
  305. {
  306.     cptr[0] = 0;
  307.     ccathex(cptr, padChr, minApnd, maxApnd, v);
  308. }
  309.  
  310.  
  311.  
  312. /*****************************************************************************/
  313.  
  314.  
  315.  
  316. #pragma segment StringUtils
  317. void    ccpynum(char *cptr, long v, short base)
  318. {
  319.     pcpynum((StringPtr)cptr, v, base);
  320.     p2c((StringPtr)cptr);
  321. }
  322.  
  323.  
  324.  
  325. /*****************************************************************************/
  326. /*****************************************************************************/
  327. /*****************************************************************************/
  328.  
  329.  
  330.  
  331. #pragma segment StringUtils
  332. long    c2dec(char *cptr, short *charsUsed)
  333. {
  334.     return(c2num(cptr, 10, charsUsed));
  335. }
  336.  
  337.  
  338.  
  339. /*****************************************************************************/
  340.  
  341.  
  342.  
  343. #pragma segment StringUtils
  344. long    c2hex(char *cptr, short *charsUsed)
  345. {
  346.     return(c2num(cptr, 16, charsUsed));
  347. }
  348.  
  349.  
  350.  
  351. /*****************************************************************************/
  352.  
  353.  
  354.  
  355. #pragma segment StringUtils
  356. long    c2num(char *cptr, short base, short *charsUsed)
  357. {
  358.     Boolean    firstDigit;
  359.     short    i, sgn;
  360.     short    c;
  361.     long    val;
  362.  
  363.     sgn = 1;
  364.     for (firstDigit = false, val = 0, i = 0;;) {
  365.         c = cptr[i++];
  366.         if (base == 256) {
  367.             if (!c) break;
  368.             if (c == '\'') {
  369.                 ++i;
  370.                 break;
  371.             }
  372.             val *= base;
  373.             val += c;
  374.             continue;
  375.         }
  376.         if (c == '-') {
  377.             if (firstDigit) break;
  378.             if (sgn == -1)  break;
  379.             sgn = -1;
  380.             continue;
  381.         }
  382.         if (c == '$') {
  383.             if (firstDigit) break;
  384.             base = 16;
  385.             continue;
  386.         }
  387.         if (gHandleChars) {
  388.             if (c == '\'') {
  389.                 if (firstDigit) break;
  390.                 base = 256;
  391.                 continue;
  392.             }
  393.         }
  394.         if ((!firstDigit) && (c == ' ')) continue;
  395.         c -= '0';
  396.         if (c > 16) c -= 7;        /* Make 'A' a 10, etc. */
  397.         if (c > 32) c -= 32;    /* Make lower-case upper-case. */
  398.         if (c < 0) break;
  399.         if (c >= base) break;
  400.         val *= base;
  401.         val += (c * sgn);
  402.         firstDigit = true;
  403.     }
  404.  
  405.     if (charsUsed) *charsUsed = --i;
  406.  
  407.     gBase = base;
  408.     return(val);
  409. }
  410.  
  411.  
  412.  
  413. /*****************************************************************************/
  414.  
  415.  
  416.  
  417. #pragma segment StringUtils
  418. short    GetLastBase(Boolean handleChars)
  419. {
  420.     gHandleChars = handleChars;
  421.     return(gBase);
  422. }
  423.  
  424.  
  425.  
  426. /*****************************************************************************/
  427. /*****************************************************************************/
  428. /*****************************************************************************/
  429.  
  430.  
  431.  
  432. /* Catenate a single character multiple times onto the designated string. */
  433.  
  434. #pragma segment StringUtils
  435. void    pcatchr(StringPtr pptr, char c, short count)
  436. {
  437.     while (count--) pptr[++(pptr[0])] = c;
  438. }
  439.  
  440.  
  441.  
  442. /*****************************************************************************/
  443.  
  444.  
  445.  
  446. #pragma segment StringUtils
  447. void    pcatdec(StringPtr pptr, long v)
  448. {
  449.     pcatnum(pptr, v, -10);
  450. }
  451.  
  452.  
  453.  
  454. /*****************************************************************************/
  455.  
  456.  
  457.  
  458. #pragma segment StringUtils
  459. void    pcathex(StringPtr pptr, char padChr, short minApnd, short maxApnd, long v)
  460. {
  461.     char    str[33];
  462.  
  463.     ccpyhex(str, padChr, minApnd, maxApnd, v);
  464.     c2p(str);
  465.     pcat(pptr, (StringPtr)str);
  466. }
  467.  
  468.  
  469.  
  470. /*****************************************************************************/
  471.  
  472.  
  473.  
  474. #pragma segment StringUtils
  475. long    pcatnum(StringPtr pptr, long v, short base)
  476. {
  477.     unsigned long    j, vv;
  478.  
  479.     vv = v;
  480.     if (base < 0) {
  481.         base = -base;
  482.         if (v < 0) {
  483.             pptr[++*pptr] = '-';
  484.             vv = -vv;
  485.         }
  486.     }
  487.     j = 0;
  488.     if (vv >= base)
  489.         j = pcatnum(pptr, vv / base, base);
  490.  
  491.     pptr[++*pptr] = "0123456789ABCDEF"[vv - j];
  492.     return(base * vv);
  493. }
  494.  
  495.  
  496.  
  497. /*****************************************************************************/
  498.  
  499.  
  500.  
  501. #pragma segment StringUtils
  502. void    pcpydec(StringPtr pptr, long v)
  503. {
  504.     *pptr = 0;
  505.     pcatdec(pptr, v);
  506. }
  507.  
  508.  
  509.  
  510. /*****************************************************************************/
  511.  
  512.  
  513.  
  514. #pragma segment StringUtils
  515. void    pcpynum(StringPtr pptr, long v, short base)
  516. {
  517.     *pptr = 0;
  518.     pcatnum(pptr, v, base);
  519. }
  520.  
  521.  
  522.  
  523. /*****************************************************************************/
  524.  
  525.  
  526.  
  527. #pragma segment StringUtils
  528. void    pcpyhex(StringPtr pptr, char padChr, short minApnd, short maxApnd, long v)
  529. {
  530.     *pptr = 0;
  531.     pcathex(pptr, padChr, minApnd, maxApnd, v);
  532. }
  533.  
  534.  
  535.  
  536. /*****************************************************************************/
  537.  
  538.  
  539.  
  540. #pragma segment StringUtils
  541. long    p2dec(StringPtr pptr, short *charsUsed)
  542. {
  543.     return(p2num(pptr, 10, charsUsed));
  544. }
  545.  
  546.  
  547.  
  548. /*****************************************************************************/
  549.  
  550.  
  551.  
  552. #pragma segment StringUtils
  553. long    p2hex(StringPtr pptr, short *charsUsed)
  554. {
  555.     return(p2num(pptr, 16, charsUsed));
  556. }
  557.  
  558.  
  559.  
  560. /*****************************************************************************/
  561.  
  562.  
  563.  
  564. #pragma segment StringUtils
  565. long    p2num(StringPtr pptr, short base, short *charsUsed)
  566. {
  567.     long    val;
  568.  
  569.     p2c(pptr);
  570.     val = c2num((char *)pptr, base, charsUsed);
  571.     c2p((char *)pptr);
  572.     return(val);
  573. }
  574.  
  575.  
  576.  
  577. /*****************************************************************************/
  578. /*****************************************************************************/
  579. /*****************************************************************************/
  580.  
  581.  
  582.  
  583. #pragma segment StringUtils
  584. short    GetHexByte(char *cptr)
  585. {
  586.     short    val, i, chr;
  587.  
  588.     for (val = 0, i = 0; i < 2; ++i) {
  589.         chr = cptr[i];
  590.         if (chr == '=') return(cptr[++i]);
  591.         if (chr == '≈') {
  592.             chr = cptr[++i];
  593.             if ((chr >= 'a') && (chr <= 'z')) chr -= 32;
  594.             return(chr);
  595.         }
  596.         if (chr > 'F')
  597.             chr -= 0x20;
  598.         if (chr > '9')
  599.             chr -= ('A' - '9' - 1);
  600.         val = (val << 4) + chr - '0';
  601.     }
  602.     return(val);
  603. }
  604.  
  605.  
  606.  
  607. /*****************************************************************************/
  608.  
  609.  
  610.  
  611. #pragma segment StringUtils
  612. Boolean    EqualHandle(void *h1, void *h2)
  613. {
  614.     long    s1, s2;
  615.     Ptr        p1, p2;
  616.  
  617.     if ((h1) && (!h2)) return(false);
  618.     if ((h2) && (!h1)) return(false);
  619.     if ((s1 = GetHandleSize(h1)) != (s2 = GetHandleSize(h2))) return(false);
  620.  
  621.     p1 = *(Handle)h1;
  622.     p2 = *(Handle)h2;
  623.     for (s1 = 0; s1 < s2; ++s1)
  624.         if (p1[s1] != p2[s1]) return(false);
  625.         
  626.     return(true);
  627. }
  628.  
  629.  
  630.  
  631. /*****************************************************************************/
  632.  
  633.  
  634.  
  635. #pragma segment StringUtils
  636. Boolean    EqualData(void *v1, void *v2, long size)
  637. {
  638.     Ptr        p1, p2;
  639.     long    ii;
  640.  
  641.     if ((v1) && (!v2)) return(false);
  642.     if ((v2) && (!v1)) return(false);
  643.  
  644.     p1 = (Ptr)v1;
  645.     p2 = (Ptr)v2;
  646.     for (ii = 0; ii < size; ++ii)
  647.         if (p1[ii] != p2[ii]) return(false);
  648.         
  649.     return(true);
  650. }
  651.  
  652.  
  653.  
  654.